# -*- coding: utf-8 -*-
"""
@File: CameraServer.py
@Time: 2021/12/24 17:14
@Author: 鹄望潇湘
@desc: 

[host, id, is_record, battery, storage, now_id, now_seq]

"""
import random
import threading
import tkinter as tk
import tkinter.messagebox
from SocketLib import SocketServer, Message


class DeviceFrame:
    def __init__(self, root, row, column):
        self.frame = tk.Frame(root, width=200, height=150)
        self.device_id = tk.Label(self.frame, text="设备ID: ", fg="red", font=('Arial', 13))
        self.state = tk.Label(self.frame, text="录制状态: ", fg="blue", font=('Arial', 13))
        self.battery = tk.Label(self.frame, text="设备电量: ", fg="green", font=('Arial', 13))
        self.storage = tk.Label(self.frame, text="存储空间: ", fg="pink", font=('Arial', 13))

        self.device_id.place(x=20, y=0)
        self.state.place(x=20, y=30)
        self.battery.place(x=20, y=60)
        self.storage.place(x=20, y=90)
        self.frame.grid(row = row, column=column)
        self.updateUI("无", "无", "0", "0")

    def updateUI(self, device_id, state, battery, storage):
        self.device_id['text'] = "设备ID: "+device_id
        self.state['text'] = "录制状态: "+state
        self.battery['text'] = "设备电量: "+battery+"%"
        self.storage['text'] = "存储空间: "+storage+"GB"


class CameraServer(SocketServer):
    DEVICE_ID = 0
    DENY_DEVICE = 1
    START_RECORD = 2
    STOP_RECORD = 3
    NEW_SEQUEENCE = 4
    UPDATE_STATE = 5
    sequeence = ["nm_01", "nm_02", "bg_01", "bg_02", "cl_01", "cl_02", "face"]

    def __init__(self, listen_ip, listen_port):
        super(CameraServer, self).__init__()
        self.devices = dict()
        self.window = tk.Tk()
        self.listen_ip = listen_ip
        self.listen_port = listen_port
        self.ui_semaphore = threading.Semaphore(1)
        self.now_server_id = ""
        self.now_server_seq = len(CameraServer.sequeence)-1
        self.init_window()
        self.on_click_next_seq()

    def init_window(self):
        self.window.title("数据采集服务端")
        self.window.geometry("800x630+600+100")
        self.frames = []
        for row in range(0, 3):
            for col in range(0, 4):
                self.frames.append(DeviceFrame(self.window, row, col))

        self.now_ID = tk.Label(self.window, text="当前ID: ", fg="black", font=('微软雅黑', 13))
        self.now_ID.place(x=20, y=500)

        self.now_sequence = tk.Label(self.window, text="当前序列: ",fg="black", font=('微软雅黑', 13) )
        self.now_sequence.place(x=220, y=500)

        self.record_state = tk.Label(self.window, text="录制状态: ", fg="black", font=('微软雅黑', 13))
        self.record_state.place(x=420, y=500)

        self.start_record = tk.Button(self.window, text="开始录制", font=('微软雅黑', 13), command=self.on_click_start)
        self.start_record.place(x=220, y=550)

        self.stop_record = tk.Button(self.window, text="停止录制", font=('微软雅黑', 13), command=self.on_click_stop)
        self.stop_record.place(x=420, y=550)

        self.next_seq = tk.Button(self.window, text="下一序列", font=('微软雅黑', 13), command=self.on_click_next_seq)
        self.next_seq.place(x=20, y=550)


    def connected(self, host):
        pass

    def disconnected(self, host):
        for key in self.devices.keys():
            states = self.devices[key]
            if self.devices[key][0] == host:
                self.devices.pop(key)
                self.updateUI()
                tk.messagebox.showinfo('设备断开', '设备'+states[1]+str(states[0])+"已断开连接！")
                return
        pass

    def message_process(self, message, host):

        info = Message.decode(message)
        try:
            code = Message.decode(info["code"])
        except:
            self.logger.info("问题host: "+host)
            return
        self.ui_semaphore.acquire()
        if code == CameraServer.DEVICE_ID:
            temp_id = Message.decode(info["device_id"])
            target = self.devices.get(temp_id)
            if target is None:
                self.devices[temp_id] = [host, temp_id, 0, 0, 0, "", ""]
                self.send_bytes(host, message)
            else:
                response = self.get_message_head(CameraServer.DENY_DEVICE)
                self.send_bytes(host, Message.encode(response))
            pass
        if code == CameraServer.UPDATE_STATE:
            device_id = Message.decode(info["device_id"])
            is_record = Message.decode(info["is_record"])
            battery = Message.decode(info["battery"])
            storage = Message.decode(info["storage"])
            person_id = Message.decode(info["person_id"])
            person_seq = Message.decode(info["person_seq"])
            states = self.devices[device_id]
            states[2] = is_record
            states[3] = battery
            states[4] = storage
            states[5] = person_id
            states[6] = person_seq
            if person_id+person_seq != self.now_server_id+CameraServer.sequeence[self.now_server_seq]:
                self.send_now_seq_to_client()
            self.updateUI()
        self.ui_semaphore.release()
        pass

    def get_message_head(self, message_type):
        result = dict()
        result["code"] = Message.encode(message_type)
        return result

    def start_window(self):
        threading.Thread(target=self.start, args=(self.listen_ip, self.listen_port)).start()
        self.window.mainloop()
        self.closeServer()
        pass

    def updateUI(self):
        device_number = len(self.devices.keys())
        for index in range(device_number, len(self.frames)):
            self.frames[index].updateUI("无", "无", "0", "0")

        have_in_record = False
        try:
            for index, item in enumerate(self.devices.keys()):
                state = self.devices[item]
                is_record = "正在录制" if state[2] == 1 else "未在录制"
                if state[2] == 1:
                    have_in_record = True
                self.frames[index].updateUI(state[1], is_record, str(state[3]), str(state[4]))
        except:
            pass
        if len(self.devices.keys()) == 0:
            have_in_record = False

        if have_in_record:
            self.stop_record['state'] = tk.NORMAL
            self.start_record['state'] = tk.DISABLED
            self.next_seq['state'] = tk.DISABLED
        else:
            self.stop_record['state'] = tk.DISABLED
            self.start_record['state'] = tk.NORMAL
            self.next_seq['state'] = tk.NORMAL

        self.now_ID['text'] = "当前ID: "+self.now_server_id
        self.now_sequence["text"] = "当前序列: "+CameraServer.sequeence[self.now_server_seq]
        self.record_state["text"] = "录制状态: "+("正在录制" if have_in_record else "未在录制")

        pass

    def on_click_start(self):
        now_person = self.now_server_id
        now_seq = CameraServer.sequeence[self.now_server_seq]
        synced = True
        for key in self.devices.keys():
            states = self.devices[key]
            if now_person+now_seq != states[5]+states[6]:
                synced = False
        if synced is False:
            self.send_now_seq_to_client()
        message = self.get_message_head(CameraServer.START_RECORD)
        # self.send_to_all_client(Message.encode(message))
        for key in self.devices.keys():
            is_record = self.devices[key][2]
            host = self.devices[key][0]
            if is_record == 0:
                self.send_bytes(host, Message.encode(message))

    def on_click_stop(self):
        message = self.get_message_head(CameraServer.STOP_RECORD)
        for key in self.devices.keys():
            is_record = self.devices[key][2]
            host = self.devices[key][0]
            if is_record==1:
                self.send_bytes(host, Message.encode(message))

    def on_click_next_seq(self):
        if self.now_server_seq == len(CameraServer.sequeence)-1:
            self.now_server_id = self.get_new_person_id()
            self.now_server_seq = 0
        else:
            self.now_server_seq += 1
        self.send_now_seq_to_client()
        self.updateUI()
        pass

    def get_new_person_id(self):
        chars = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz'
        return ''.join(random.choice(chars) for _ in range(8))

    def send_now_seq_to_client(self):
        id = self.now_server_id
        seq = CameraServer.sequeence[self.now_server_seq]
        message = self.get_message_head(CameraServer.NEW_SEQUEENCE)
        message['person'] = Message.encode(id)
        message['type'] = Message.encode(seq)
        message = Message.encode(message)
        self.send_to_all_client(message)

    def send_to_all_client(self, data):
        for key in self.devices.keys():
            host = self.devices[key][0]
            self.send_bytes(host, data)